package com.ctshk.rpc.localfun.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ctshk.common.dto.Result;
import com.ctshk.common.enums.ScenicTicketStatus;
import com.ctshk.common.model.PageResponse;
import com.ctshk.common.utils.EntityUtil;
import com.ctshk.common.utils.SnowflakeIdWorker;
import com.ctshk.rpc.localfun.dto.LocalFunResourceDownBox;
import com.ctshk.rpc.localfun.dto.LocalFunResourceTicketDTO;
import com.ctshk.rpc.localfun.entity.LocalFunProductCostStrategySpecStock;
import com.ctshk.rpc.localfun.entity.LocalFunProductTicket;
import com.ctshk.rpc.localfun.mapper.LocalFunProductCostStrategySpecStockMapper;
import com.ctshk.rpc.localfun.mapper.LocalFunProductTicketMapper;
import com.ctshk.rpc.localfun.req.LocalFunResourceTicketReq;
import com.ctshk.rpc.localfun.service.ILocalFunResourceTicketService;
import com.github.xiaoymin.knife4j.core.util.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @Description
 * @Author wansi <gaylen15527491065@yeah.net>
 * @Date 2021/3/29
 */
@DubboService
public class LocalFunResourceTicketServiceImpl extends ServiceImpl<LocalFunProductTicketMapper,LocalFunProductTicket> implements ILocalFunResourceTicketService {

    @Autowired
    private LocalFunProductCostStrategySpecStockMapper scenicProductCostStrategySpecStockMapper;

    @Override
    @Transactional(isolation = Isolation.SERIALIZABLE)
    public Result<Long> createTicket(Long productId) {
        QueryWrapper<LocalFunProductCostStrategySpecStock> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(LocalFunProductCostStrategySpecStock::getProductId, productId);

        List<LocalFunProductCostStrategySpecStock> scenicProductCostStrategySpecStocks = scenicProductCostStrategySpecStockMapper.selectList(queryWrapper);
        scenicProductCostStrategySpecStocks.forEach(scenicProductCostStrategySpecStock -> {
            QueryWrapper<LocalFunProductTicket> ticketQueryWrapper = new QueryWrapper<>();
            ticketQueryWrapper.lambda().select(LocalFunProductTicket::getStockNumber).like(LocalFunProductTicket::getStockNumber, scenicProductCostStrategySpecStock.getStockNumber());

            List<LocalFunProductTicket> scenicProductTickets = baseMapper.selectList(ticketQueryWrapper);
            int maxNum = 0;
            int i = 1;
            Integer totalStock = scenicProductCostStrategySpecStock.getTotalStock();
            if (CollectionUtils.isNotEmpty(scenicProductTickets)) {
                totalStock = totalStock - scenicProductTickets.size();
                Optional<Integer> max = scenicProductTickets.stream().map(ticket -> {
                    String numStr = ticket.getStockNumber().substring(ticket.getStockNumber().length() - 4);
                    return Integer.parseInt(numStr);
                }).max(Integer::compare);
                if (max.isPresent()) {
                    maxNum = max.get();
                }
            }
            List<LocalFunProductTicket> scenicProductTicketList = new ArrayList<>();
            while (i <= totalStock) {
                LocalFunProductTicket scenicProductTicket = EntityUtil.convertBean(scenicProductCostStrategySpecStock, LocalFunProductTicket.class);
                scenicProductTicket.setId(SnowflakeIdWorker.nextId());
                scenicProductTicket.setStockId(scenicProductCostStrategySpecStock.getId());
                int newStockNum = maxNum + i;
                scenicProductTicket.setStockNumber(scenicProductCostStrategySpecStock.getStockNumber() + String.format("%04d", newStockNum));
                scenicProductTicket.setStatus(ScenicTicketStatus.UNSOLD.getCode());
                scenicProductTicketList.add(scenicProductTicket);
                i++;
            }
            try {
                super.saveBatch(scenicProductTicketList);
            } catch (Exception ignored) {}
        });
        return Result.success(productId);
    }

    @Override
    public PageResponse<LocalFunResourceTicketDTO> queryList(LocalFunResourceTicketReq resourceTicketReq) {

        IPage<LocalFunProductTicket> iPage = new Page<>(resourceTicketReq.getPageNo(), resourceTicketReq.getPageSize());

        QueryWrapper<LocalFunProductTicket> queryWrapper = new QueryWrapper<>();

        queryWrapper.lambda().eq(LocalFunProductTicket::getProductId, resourceTicketReq.getProductId());

        if (null != resourceTicketReq.getAttr1Id()) {
            queryWrapper.lambda().eq(LocalFunProductTicket::getAttr1Id, resourceTicketReq.getAttr1Id());
        }
        if (null != resourceTicketReq.getAttr2Id()) {
            queryWrapper.lambda().eq(LocalFunProductTicket::getAttr2Id, resourceTicketReq.getAttr2Id());
        }
        if (StringUtils.isNotEmpty(resourceTicketReq.getStockNumber())) {
            queryWrapper.lambda().like(LocalFunProductTicket::getStockNumber, resourceTicketReq.getStockNumber());
        }
        if (StringUtils.isNotEmpty(resourceTicketReq.getSupplierTicketNumber())) {
            queryWrapper.lambda().like(LocalFunProductTicket::getSupplierTicketNumber, resourceTicketReq.getSupplierTicketNumber());
        }
        if (StringUtils.isNotEmpty(resourceTicketReq.getDepartmentName())) {
            queryWrapper.lambda().like(LocalFunProductTicket::getDepartmentName, resourceTicketReq.getDepartmentName());
        }
        if (null != resourceTicketReq.getStatus()) {
            queryWrapper.lambda().eq(LocalFunProductTicket::getStatus, resourceTicketReq.getStatus());
        }

        IPage<LocalFunProductTicket> scenicProductTicketIPage = baseMapper.selectPage(iPage, queryWrapper);
        if (CollectionUtils.isNotEmpty(scenicProductTicketIPage.getRecords())) {
            List<LocalFunResourceTicketDTO> scenicResourceTicketDTOS = EntityUtil.copyList(scenicProductTicketIPage.getRecords(), LocalFunResourceTicketDTO.class);
            return new PageResponse<>(scenicResourceTicketDTOS, iPage.getCurrent() == 1, iPage.getTotal() <= (iPage.getCurrent() * iPage.getSize()), iPage.getTotal(), iPage.getCurrent(), iPage.getSize());
        }
        return new PageResponse<>(new ArrayList<>(), iPage.getCurrent() == 1, iPage.getTotal() <= (iPage.getCurrent() * iPage.getSize()), iPage.getTotal(), iPage.getCurrent(), iPage.getSize());
    }

    @Override
    public Result<List<LocalFunResourceDownBox>> downBox(Long productId) {
        QueryWrapper<LocalFunProductCostStrategySpecStock> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(LocalFunProductCostStrategySpecStock::getProductId, productId);
        List<LocalFunProductCostStrategySpecStock> scenicProductCostStrategySpecStocks = scenicProductCostStrategySpecStockMapper.selectList(queryWrapper);
        return Result.success(EntityUtil.copyList(scenicProductCostStrategySpecStocks, LocalFunResourceDownBox.class));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<Long> updateStatus(List<Long> ids, ScenicTicketStatus status) {
        List<LocalFunProductTicket> list = baseMapper.selectBatchIds(ids).stream()
                .filter(item -> item.getStatus().equals(ScenicTicketStatus.SOLD.getCode())).peek(item -> {
                    item.setSupplierTicketNumber(null);
                    item.setDepartmentId(null);
                    item.setDepartmentName(null);
                    item.setSalerId(null);
                    item.setSalerName(null);
                    item.setSaleNumber(null);
                    item.setStatus(status.getCode());
                }).collect(Collectors.toList());
        super.saveOrUpdateBatch(list);
        list.stream().map(LocalFunProductTicket::getStockId)
                .distinct()
                .forEach(stockId -> {
                    LocalFunProductTicket scenicProductTicket = new LocalFunProductTicket();
                    scenicProductTicket.setStockId(stockId);
                    QueryWrapper<LocalFunProductTicket> queryWrapper = new QueryWrapper<>();
                    queryWrapper.lambda().eq(LocalFunProductTicket::getStockId, stockId);
                    queryWrapper.lambda().eq(LocalFunProductTicket::getStatus, ScenicTicketStatus.SOLD.getCode())
                            .or().eq(LocalFunProductTicket::getStatus, ScenicTicketStatus.UNSOLD.getCode());
                    LocalFunProductCostStrategySpecStock scenicProductCostStrategySpecStock = scenicProductCostStrategySpecStockMapper.selectById(stockId);
                    scenicProductCostStrategySpecStock.setTotalStock(baseMapper.selectCount(queryWrapper));
                    scenicProductCostStrategySpecStockMapper.updateById(scenicProductCostStrategySpecStock);
                });
        return Result.success(ids.get(0));
    }

}
